// GSP410 Chris Dickinson & Joe Lang
// Hammurabi Game class

#pragma once

#include "time.h"
#include <iostream>
#include <time.h>
#include "ServerInterface.h"
#include "..\Shared\Message.h"
#include "..\Shared\PlayerInformation.h"
#include "..\Shared\LRSInformation.h"
#include "..\Shared\GalaxyMap.h"
#include "..\Shared\SectorMap.h"

#define _SPACESHOOTERDEBUGMESSAGES_

#define MESSAGE_DELAY	0.05f

#define ENERGYCOST_STARTMOVE				10
#define ENERGYCOST_MOVEONESUBSECTOR			2
#define ENERGYCOST_DRAINPENALTYFACTOR		2
#define	MOVESECTOR_MAXDIST					8

#define ENERGYTRANSFER_PERCLICK				100

#define RNG_1ENEMYSHIP		20
#define RNG_2ENEMYSHIPS		5
#define RNG_3ENEMYSHIPS		2
#define RNG_1SPACESTATION	4
#define RNG_STARSMAX		7

#define RNG_SPACESTATIONMIN	1
#define RNG_ENEMYSHIPSMIN	5

#define REPAIRRATE_UNDOCKED	1
#define REPAIRRATE_DOCKED	(rand() % 1 + 1)

#define CRITICAL_DAMAGE_FACTOR	0.2	// fraction of shield that damage needs to exceed to cause critical damage
#define CRITICAL_DAMAGE_CHANCE_FULL_SHIELD	5	// chance of critical damage occuring if shields absorbed most of it
#define CRITICAL_DAMAGE_CHANCE_NO_SHIELD	40	// chance of critical damage occuring if no shields to absorb

class SpaceShooterGame
{
private:
	std::vector<Message*>	mQueue;
	float					mTimeSinceSentLastMessage;

	// time handling with the performance timer
	__int64					mPrevTimeStamp;
	float					mSecsPerCount;
	
	GalaxyMap				mGalaxyMap;		// galaxymap
	SectorMap				mSectorMap;
	Coordinate				mCurrentSector;	//currentSector
	PlayerInformation		mPlayerInfo;	// struct to store the player's current state

	// these variables are used to keep track of how much energy is consumed
	// during a move/attack calculation.
	int mMoveEnergyConsumed;
	int mMoveBlastersConsumed;
	int mMoveShieldsConsumed;
	int mDamageEnergyConsumed;
	int mDamageShieldsConsumed;
	int mDamageBlastersConsumed;

	int						mNumSpaceStations;
	int						mNumEnemies;

	bool					mPlayerInfoChanged;
	
public:
	SpaceShooterGame();
	~SpaceShooterGame();

	void InitGame();
	void InitializePlayerInfo();
	void InitializeMap();
	void SendStartupMessages();
	

	// processes incoming messages from the server
	void ProcessMessage(Message* msg);

	// Functions for each input message
	void IncreaseBlasters(Message* msg);
	void DecreaseBlasters(Message* msg);
	void IncreaseShields(Message* msg);
	void DecreaseShields(Message* msg);
	void LeftClickedCoordinate(Message* msg);
	void HyperdriveToCoordinate(Message* msg);

	// secondary functions
	void FireBlasters();
	void Undock();
	void WaitOneTurn();
	void Restart();
	void FireMissile(Coordinate target);
	void MoveToDock(Coordinate target);
	void MoveToSubsector(Coordinate destination, bool initialized = false);
	void MoveToSector(Coordinate destination, bool initialized = false);
	void ConsumeEnergy(int energyCost);
	void DealDamageToPlayer(int damage);
	void UpdateLRSAtPlayerLocation(ObjectType type);
	void DamageEnemyShipAtLocation(Coordinate location, int damage = 0);
	void DestroySpaceStationAtLocation(Coordinate location);
	void ResupplyAndRepair();
	void PerformRepairs(int repairRate);
	void EndTurn(void);
	void UpdateLRSKnowledge(bool initialized = false);
	void EnemyAttack(void);
	void ResetEnergyConsumption(void);
	void NotifyEnergyConsumption(void);
	void CriticalDamage(void);
	
	// add an event to the queue
	void QueueMessage(Message* msg);

	// create a basic message using the given type
	Message* CreateMessage(MessageType type);
	Message* CreateMessage(MessageType type, Coordinate c);
	Message* CreateMessage(MessageType type, Coordinate c, ObjectType objType);
	Message* CreateMessage(PlayerInformation info);
	Message* CreateMessage(LRSInformation info, Coordinate c);
	Message* CreateMessage(MessageType type, Coordinate c, int integer);
	Message* CreateMessage(MessageType type, int integer);

	// used by serverinterface to get the latest message to send
	Message* GetQueuedMessage(void);



};